//筛质数
//朴素做法：如果k是质数，那么其不是2~k-1的倍数，依次从前往后遍历,时间复杂度：O(lnn + c),调和级数
//埃氏做法：只要不是前面质数的倍数即可, 时间复杂度：O(nloglogn);
//线性做法： 依次找质数，为避免重复判断，需要再做优化，以最小质因子为判断标准，时间复杂度:O(n)

#include<iostream>
using namespace std;

const int N = 1e6+10;
int n, cnt;
//prime数组存储的是从小到大的质数
int prime[N];
//st数组用来判断一个数是不是质数
bool st[N];

void find(int n)
{
    for(int i = 2; i <= n; ++i)
    {
        if(!st[i]) prime[cnt++] = i;
        for(int j = 0; prime[j] <= n / i; ++j)
        {
            //上面这个是分情况讨论的
            //构成这种情况的原因是质数的存储是从小到大存储的
            //如果i%prime[j]!=0, 那么prime[j]小于其最小质因数，但是一定是prime[j]*i的最小质因数
            //如果i%prime[j]==0, 那么prime[j]是其最小质因数，也一定是prime[j]*i的最小质因数
            st[prime[j]*i] = true;
            if(i % prime[j] == 0) break;
        }
    }
}

//埃氏算法
/*void find(int n)
{
    for(int i = 2; i <= n; ++i)
    {
        if(!st[i])
        {
            cnt++;
            for(int j = 2*i; j <= n; j+=i) st[j] = true;
        }
    }
}*/

int main()
{
    cin >> n;
    find(n);
    cout << cnt;
    return 0;
}
